import base64
import hashlib

import bcrypt

from ...db import models as db
from ...db.util import transaction
from ..base import BaseProcessor
from ..util import get_parameter
from ...exceptions import MissingParameterError, MobileDuplicatedError


def hashpw(password):
    """加密密码
    """
    hashed = bcrypt.hashpw(
        base64.b64encode(hashlib.sha256(password.encode('utf-8')).digest()),
        bcrypt.gensalt()
    )
    return hashed


def checkpw(password, hashed):
    """校验密码
    """
    return bcrypt.checkpw(password, hashed)


class UserProcessor(BaseProcessor):
    """用户基本资料/users

    Auto Generated Code.
    """
    @transaction()
    def create(self, *args, **kwargs):
        """mobile/nickname/password
        """
        if 'mobile' not in kwargs:
            raise MissingParameterError('mobile is missing')
        if 'nickname' not in kwargs:
            raise MissingParameterError('nickname is missing')
        if 'password' not in kwargs:
            raise MissingParameterError('password is missing')

        if 'mobile' in kwargs:
            mobile = kwargs.get('mobile')
            if self._read(mobile=mobile):
                raise MobileDuplicatedError('mobile {}'.format(mobile))

        if 'nickname' in kwargs:
            nickname = kwargs.get('nickname')
            if self._read(nickname=nickname):
                raise NicknameDuplicatedError('nickname {}'.format(nickname))

        # password => bcrypt => hashed
        if 'password' in kwargs:
            kwargs['password'] = hashpw(kwargs['password'])

        obj = db.User(**kwargs)
        self.dbh.add(obj)
        return obj

    @transaction()
    def read(self, *args, **kwargs):
        return self._read(*args, **kwargs)
   
    def _read(self, *args, **kwargs):
        """userID/userid > nickname > mobile
        """
        isfilter = False
        q = self.dbh.query(db.User)

        userid = get_parameter(kwargs, ('userID', 'userid'))
        if userid is not False:
            isfilter = True
            q = q.filter(db.User.userid == userid)

        nickname = get_parameter(kwargs, 'nickname')
        if nickname is not False:
            isfilter = True
            q = q.filter(db.User.nickname == nickname)

        mobile = get_parameter(kwargs, 'mobile')
        if mobile is not False:
            isfilter = True
            q = q.filter(db.User.mobile == mobile)

        if isfilter:
            return q.first()

        return None

    def update(self, *args, **kwargs):
        raise NotImplementedError

    def delete(self, *args, **kwargs):
        raise NotImplementedError
